﻿using System;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
using System.Windows.Markup;
using ICodeShare.UI.Converters.Extensions;
using ICodeShare.UI.Converters.Helpers;

namespace ICodeShare.UI.Converters
{
    #region IValueConverter,IMultiValueConverter
    /// <summary>
    /// 格式化字符串输出转换器,根据对输入进行格式化字符串转换
    /// </summary>   
    /// <example>
    /// 1.在xmal文件引用DateConverter类所在命名空间。
    ///   xmlns:cvts="http://schemas.extended.wpf.com/converters"
    /// 2.在xaml文件添加Resources。
    ///   <Window.Resources>
    ///   <cvts:StringFormatConverter x:Key="cvtsStringFormat"/>
    ///   </Window.Resources>
    /// 3.在xaml文件中指定Binding值的Converter
    /// <TextBox Text="{Binding ShowTheText,Converter={StaticResource cvtsStringFormat}}"></TextBox>
    /// </example>
    [ContentProperty("FormatString")]
    [ValueConversion(typeof(object), typeof(string))]
    public sealed class StringFormatConverter : IValueConverter, IMultiValueConverter
    {
        private static readonly ExceptionHelper exceptionHelper = new ExceptionHelper(typeof(StringFormatConverter));
        private string formatString;

        /// <summary>
        /// Initializes a new instance of the StringFormatConverter class.
        /// </summary>
        public StringFormatConverter()
        {
        }

        /// <summary>
        /// Initializes a new instance of the StringFormatConverter class with the specified format string.
        /// </summary>
        /// <param name="formatString">
        /// The format string.
        /// </param>
        public StringFormatConverter(string formatString)
        {
            this.FormatString = formatString;
        }

        /// <summary>
        /// Gets or sets the format string to use when converting bound data.
        /// </summary>
        [ConstructorArgument("formatString")]
        public string FormatString
        {
            get { return this.formatString; }
            set { this.formatString = value; }
        }

        /// <summary>
        /// Attempts to convert the specified value.
        /// </summary>
        /// <param name="value">
        /// The value to convert.
        /// </param>
        /// <param name="targetType">
        /// The type of the binding target property.
        /// </param>
        /// <param name="parameter">
        /// The converter parameter to use.
        /// </param>
        /// <param name="culture">
        /// The culture to use in the converter.
        /// </param>
        /// <returns>
        /// A converted value.
        /// </returns>
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            exceptionHelper.ResolveAndThrowIf(this.FormatString == null, "NoFormatString");
            return string.Format(culture, this.FormatString, value);
        }

        /// <summary>
        /// Attempts to convert the specified value back.
        /// </summary>
        /// <param name="value">
        /// The value to convert.
        /// </param>
        /// <param name="targetType">
        /// The type of the binding target property.
        /// </param>
        /// <param name="parameter">
        /// The converter parameter to use.
        /// </param>
        /// <param name="culture">
        /// The culture to use in the converter.
        /// </param>
        /// <returns>
        /// A converted value.
        /// </returns>
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            value.AssertNotNull("targetType");

            try
            {
                return System.Convert.ChangeType(value, targetType, culture);
            }
            catch (Exception)
            {
                return DependencyProperty.UnsetValue;
            }
        }

        /// <summary>
        /// Attempts to convert the specified values.
        /// </summary>
        /// <param name="values">
        /// The values to convert.
        /// </param>
        /// <param name="targetType">
        /// The type of the binding target property.
        /// </param>
        /// <param name="parameter">
        /// The converter parameter to use.
        /// </param>
        /// <param name="culture">
        /// The culture to use in the converter.
        /// </param>
        /// <returns>
        /// A converted value.
        /// </returns>
        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            exceptionHelper.ResolveAndThrowIf(this.FormatString == null, "NoFormatString");
            return string.Format(culture, this.FormatString, values);
        }

        /// <summary>
        /// Attempts to convert back the specified values.
        /// </summary>
        /// <param name="value">
        /// The value to convert.
        /// </param>
        /// <param name="targetTypes">
        /// The types of the binding target properties.
        /// </param>
        /// <param name="parameter">
        /// The converter parameter to use.
        /// </param>
        /// <param name="culture">
        /// The culture to use in the converter.
        /// </param>
        /// <returns>
        /// Converted values.
        /// </returns>
        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
        {
            return null;
        }
    }
    #endregion
}
